/**
 * @file device_key.h
 * @author canrad (1517807724@qq.com)
 * @brief 这个模块负责独立按键的读取，不包括IO口的初始化，因此在使用之前请保证硬件已经初始化完成。
 *  使用方法：1. 创建key_t结构体类型的按键对象，并初始化
 *           2. 使用key_add将按键添加到按键列表中
 *           3. 使用key_scan扫描按键列表中的所有按键，不过要注意，按键扫描并不会阻塞
 *  参考代码：
 *      key_t   g_key1 = DEVICE_KEY_INITIALIZER(GPIOA, GPIO_PIN_0, KEY_VALUE_1, VALID_ON_LOW_LEVEL);
 *      int32_t val    = key_scan();
 *      switch (val) {
 *      case KEY_VALUE_1:
 *          // do something
 *          break;
 *      default: break;
 *      }
 *
 *
 *  未来可能加入按键状态
 *  // 按键的状态，按键的按下和释放
 *  typedef enum
 *  {
 *      key_state_none    = 0x00,
 *      key_state_press   = 0x01,   // 按键按下
 *      key_state_release = 0x02,   // 按键释放
 *  } key_state;
 *
 * @version 1.0
 * @date 2024-08-16
 *
 * @copyright Copyright (c) 2024
 *
 */
#ifndef MYLIB_DEVICE_KEY_H
#define MYLIB_DEVICE_KEY_H

#include <mylib/mylib_config.h>

// 按键列表支持的最大的按键数量
#define KEY_LIST_MAX_SIZE 10

// 键值，按键值通常是一个正数
#define KEY_VALUE_NONE 0
#define KEY_VALUE_1 1
#define KEY_VALUE_2 2
#define KEY_VALUE_3 3
#define KEY_VALUE_4 4

#if PLATFORM_STM32
typedef struct
{
    GPIO_TypeDef* port;
    uint32_t      pin;
    int32_t       key_val;   // 按键值，按键值通常是一个正数
    int8_t valid;   // 标明这个按键是什么时候按下，如果为VALID_ON_HIGH_LEVEL，说明是高电平为有效
} key_t;
#elif PLATFORM_MSPM0
typedef struct
{
    GPIO_Regs* port;
    uint32_t   pin;
    int32_t    key_val;   // 按键值，按键值通常是一个正数
    int8_t valid;   // 标明这个按键是什么时候按下，如果为VALID_ON_HIGH_LEVEL，说明是高电平为有效
} key_t;
#endif

// 设备对象初始化器
#define DEVICE_KEY_INITIALIZER(_port, _pin, _key_val, _valid) \
    {                                                         \
        .port    = _port,                                     \
        .pin     = _pin,                                      \
        .key_val = _key_val,                                  \
        .valid   = _valid,                                    \
    }

// 将一个按键添加到按键列表中
bool key_add(key_t* key);
// 扫描按键，返回按下的按键值，如果没有按键按下，则返回
int32_t key_scan(void);

#endif   // !MYLIB_DEVICE_KEY_H
